package com.xayy.health.mgt.task;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.xayy.health.mgt.model.HealthAssessTask;
import com.xayy.health.mgt.model.vo.CalculateNodeVo;
import com.xayy.health.mgt.model.vo.CalculateVo;
import com.xayy.health.mgt.service.HealthAssessResultService;
import com.xayy.health.mgt.service.HealthAssessTaskService;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author Nie
 * @version V1.0 @ Date 2024/6/6 14:45
 */
@Slf4j
@Component
@EnableScheduling
public class HealthTask {

    @Autowired
    private HealthAssessTaskService healthAssessTaskService;
    @Autowired
    private HealthAssessResultService healthAssessResultService;

    //自定义线程池
    ThreadPoolExecutor ThreadPool = new ThreadPoolExecutor(
            10,//核心线程数
            30,//最大线程数
            10,//超时时间
            TimeUnit.SECONDS,//超时时间单位
            new ArrayBlockingQueue<>(20),//阻塞队列，长度为3
            Executors.defaultThreadFactory(),//默认线程工厂
            new ThreadPoolExecutor.AbortPolicy()//拒绝策略：丢弃
    );


    /**
     * 批量预处理上线运行
     */
    @SneakyThrows
    @Scheduled(fixedDelay = 30000)
    public void online() {
        List<HealthAssessTask> taskInfos =
            healthAssessTaskService.select(HealthAssessTask.builder().taskState(1).build());
        if (CollUtil.isNotEmpty(taskInfos)) {
            taskInfos.forEach((x) -> {
                DateTime now = DateUtil.date();
                Calendar startTime = Calendar.getInstance();
                Calendar taskNow = Calendar.getInstance();
                startTime.setTime(x.getTaskCurrentTime());
                if (x.getLastTaskTime() == null) {
                    x.setLastTaskTime(x.getTaskStartTime());
                }
                taskNow.setTime(x.getLastTaskTime());
                switch (x.getTaskPeriodType()) {
                    case 0: {
                        startTime.add(Calendar.MINUTE, x.getTaskPeriod());
                        taskNow.add(Calendar.MINUTE, x.getTaskPeriod());
                        break;
                    }
                    case 1: {
                        startTime.add(Calendar.HOUR_OF_DAY, x.getTaskPeriod());
                        taskNow.add(Calendar.HOUR_OF_DAY, x.getTaskPeriod());
                        break;
                    }
                    case 2: {
                        startTime.add(Calendar.DAY_OF_MONTH, x.getTaskPeriod());
                        taskNow.add(Calendar.DAY_OF_MONTH, x.getTaskPeriod());
                        break;
                    }
                    default:
                        return;
                }
                Date endTime = taskNow.getTime();
                // 当前时间大于等于下个周期得开始时间执行任务
                int compare = DateUtil.compare(now, endTime);
                if (compare >= 0) {
                    // 执行自动任务
                    CalculateNodeVo calculateNodeVo = new CalculateNodeVo();
                    calculateNodeVo.setSatId(x.getSatelliteMid());
                    calculateNodeVo.setSatName(x.getSatelliteName());
                    calculateNodeVo.setParentId(0L);
                    calculateNodeVo.setComponentId(x.getSatelliteMid());
                    calculateNodeVo.setComponentName(x.getSatelliteName());
                    calculateNodeVo.setFractionStartTime(x.getTaskCurrentTime());
                    calculateNodeVo.setFractionTime(startTime.getTime());
                    ThreadPool.execute(() -> {
                        log.info("线程池执行任务");
                        healthAssessResultService.calculateSatellitePerformance(calculateNodeVo);
                    });
                    x.setTaskCurrentTime(startTime.getTime());
                    x.setLastTaskTime(now);
                    healthAssessTaskService.updateById(x);
                }
            });
        }
    }
}
